Skip to content

Conversation

@Jikoo
Copy link
Owner

@Jikoo Jikoo commented Jan 10, 2026

Trades a relatively small amount of disk space (about 50 bytes per player) and additional async processing post-login (which is generally a hot area for plugins already) in exchange for not relying on the server's user cache or having to load every single player from disk to check their name.

There is one behavioral change here - for the SQLite implementation, I opted to require the first character to match (case-insensitive) as it provides a massive speedup to the already-much-faster query.

TODO:

  • Expose PlayerLoader's ProfileStore getter and setter to allow third party implementation (and make sure to log w/ class when used!)
    • I've elected to not make this official API for now because I'm still on the fence about it. I will likely not resolve this until I also expose allowing custom player loader implementations.
  • Consider refactoring JdbcProfileStore
    • Removed; it would have to be rewritten to handle connection pooling anyway.
  • Consider refactoring importer to allow importing from arbitrary other implementations
    • Requires a getAllProfiles method
    • Given that this is not going to be official API yet, I don't want to bother for now. There will likely need to be events created for starting and finishing imports and things of that nature.
  • Consider adding a method to get profile by UUID
    • Just get the player directly
  • Consider adding profile expiration
    • last_update exists for this
    • For now I don't want to bother with expiration. I don't see it as a particularly desirable thing to force lookup via UUID for profiles over a certain age. People who are interested can manually run a delete query using the provided field.
  • Consider WAL
    • WAL offers a not-insignificant performance improvement. During normal operations, we only ever write with the one connection. Needs extra handling during shutdown.
    • After some consideration, I don't want to use WAL. While the database location currently is not configurable, I could see several server instances behind BungeeCord et al using the same database. Using WAL would cause a lot of extra headache there. Users who do want to enable WAL are free to do so manually.

It may be a good idea to optimize the JaroWinkler implementation in a future PR - that's likely the largest bottleneck now.

Jikoo added 10 commits January 3, 2026 17:40
The SQLite exact online should be fine(tm) to use on the main thread.
Bit torn on queries being inline rather than all declared at the top of the file. I feel like it looks less clean, but also I kept having to scroll up and down to see which index was which.
Should probably autoformat this whole thing, but eh. Some of it is even uglier autoformatted.
Jikoo added 5 commits January 10, 2026 23:40
These are not official API for now, and likely won't be until OI v6, which is still a ways out.
Helps reduce the risk of data loss during high activity.
Helps to have the UUID bits in the correct order, I'm told.
@Jikoo Jikoo marked this pull request as ready for review January 15, 2026 05:58
@Jikoo
Copy link
Owner Author

Jikoo commented Jan 15, 2026

I've tested this and it appears to be working correctly. There are a couple of things I'm not super thrilled with at the moment.

  • When importing, the final batch is not completed before the importer reports itself done. It is enqueued, but there is no guarantee that it will actually complete successfully. I imagine in that case writing completion state would also fail, so I'm not sure I want to bother changing it. Completion is another case I had missed being a race condition for WAL as well, so I feel better about having opted not to go for it.
  • When performing a batch, any new entries added between the start of the batch actually being prepared and the batch being completed are stuck enqueued until another element is added or the server shuts down. This is unlikely to be an issue aside from very specific situations like trying to open a first-time player who logged in and out right at the end of data importing. I will likely change this to attempt to re-queue anyway, assuming that the server is shutting down and the sync save will kick in if scheduling fails.

/e: Actually this is a pretty large problem because it means that the import process might leave a lot of stuff hanging depending on timing. In general, importing should probably bypass the normal batch gather and potentially do its own batching. I had wanted to create a more general solution, but getting slightly more specific seems smarter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace OfflinePlayer or improve upon it Improve offline search cache Option to disable offline player matching

2 participants